﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ElectronicCommerce.Framework.Configuration;
using ElectronicCommerce.Framework.Payment.Configuration;
using ElectronicCommerce.Framework.Payment.Contract.DataContract;
using ElectronicCommerce.Framework.Payment.Contract.DataContract.Common;
using ElectronicCommerce.Framework.Payment.Contract.ServiceContract;
using ElectronicCommerce.Framework.Payment.Data;
using ElectronicCommerce.Framework.Reflection;

namespace ElectronicCommerce.Framework.Payment.Service
{
    /// <summary>
    /// 
    /// </summary>
    public class PaymentService : IPaymentService
    {
        /// <summary>
        /// 获取所有支付方式 
        /// </summary>
        /// <returns></returns>
        public List<PaymentMethod> GetPaymentMethods()
        {
            List<PaymentMethod> paymentMethods = new List<PaymentMethod>();

            PaymentModeCollection paymentModes = ConfigManager.GetConfig<PaymentConfig>().PaymentModes;
            if (paymentMethods != null)
            {
                foreach (PaymentMode paymentMode in paymentModes)
                {
                    paymentMethods.Add(new PaymentMethod()
                    {
                        Code = paymentMode.Code,
                        Name = paymentMode.Name,
                        Description = paymentMode.Description,
                        PayRate = paymentMode.PayRate,
                        IsOnlinePay = paymentMode.IsOnlinePay,
                        IsActive = paymentMode.IsActive
                    });
                }
            }

            return paymentMethods;
        }

        /// <summary>
        /// 收费
        /// </summary>
        /// <param name="paymentType">支付类型(如:Alipay)</param>
        /// <param name="order">订单信息</param>
        public ChargeRequest Charge(ChargeRequest paymentRequest)
        {
            // 动态加载支付模块
            IPaymentService paymentService = GetPaymentService(paymentRequest);

            // 执行收费
            return paymentService.Charge(paymentRequest);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ChargeCallbackResult ChargeCallback(ChargeCallbackRequest callbackRequest)
        {
            // 动态加载支付模块
            IPaymentService paymentService = GetPaymentService(callbackRequest);

            // 执行收费
            ChargeCallbackResult innerCallbackResult = paymentService.ChargeCallback(callbackRequest);
            innerCallbackResult.Gateway = callbackRequest.Gateway;

            // 记录响应日志
            PaymentLogger.LogPaymentResponse(innerCallbackResult);

            return innerCallbackResult;
        }

        /// <summary>
        /// 如果支付请求中已经给NotifyUrl赋值，则可以在接收网关的收费处理之后，对处理结果进行回应
        /// </summary>
        /// <param name="callbackResult"></param>
        public void NotifyGatewayChargeResult(ChargeCallbackResult callbackResult)
        {
            // 动态加载支付模块
            IPaymentService paymentService = GetPaymentService(callbackResult);

            // 通知Gateway收费结果
            paymentService.NotifyGatewayChargeResult(callbackResult);
        }

        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="refundRequest"></param>
        public RefundResult Refund(RefundRequest refundRequest)
        {
            // 动态加载支付模块
            IPaymentService paymentService = GetPaymentService(refundRequest);

            // 执行收费
            RefundResult refundResult = paymentService.Refund(refundRequest);

            // 记录退款日志
            PaymentLogger.LogRefundHistory(refundRequest, refundResult);

            return refundResult;
        }

        #region Helper

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paymentRequest"></param>
        /// <returns></returns>
        private IPaymentService GetPaymentService(PaymentRequest paymentRequest)
        {
            PaymentMode paymentMode = null;
            IPaymentService paymentService = GetPaymentService(paymentRequest.Gateway.Code, out paymentMode);

            if (paymentRequest.GetwayAndSellerInfoIsFromConfig)
            {
                paymentRequest.EnvType = paymentMode.EnvType;
                paymentRequest.Seller.Code = paymentMode.SellerCode;
                paymentRequest.Seller.Email = paymentMode.SellerEmail;
                paymentRequest.Seller.Key = paymentMode.SellerKey;
                paymentRequest.Gateway.Name = paymentMode.Name;
                paymentRequest.Gateway.RequestType = paymentMode.RequestType;
                paymentRequest.Gateway.CallbackRequestType = paymentMode.CallbackRequestType;
                paymentRequest.ContentEncoding = paymentMode.ContentEncoding;
            }

            return paymentService;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paymentResult"></param>
        /// <returns></returns>
        private IPaymentService GetPaymentService(PaymentResult paymentResult)
        {
            PaymentMode paymentMode = null;
            return GetPaymentService(paymentResult.Gateway.Code, out paymentMode);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="gatewayName"></param>
        /// <returns></returns>
        private IPaymentService GetPaymentService(string gatewayName, out PaymentMode paymentMode)
        {
            // 从配置文件中获取支付网关信息
            paymentMode = ConfigManager.GetConfig<PaymentConfig>().PaymentModes.GetPaymentMode(gatewayName);
            if (paymentMode == null)
            {
                throw new PaymentException(PaymentExceptionType.LoadConfigFail,
                    string.Format(Resources.LoadConfigFail, gatewayName));
            }

            if (paymentMode.Type == null)
            {
                throw new PaymentException(PaymentExceptionType.LoadPayEntryTypeFail,
                    string.Format(Resources.LoadPayEntryTypeFail, paymentMode.TypeFullName));
            }

            // 根据支付请求动态加载相应的支付处理模块
            IPaymentService payEntry = null;
            try
            {
                payEntry = MethodCaller.CreateInstance(paymentMode.Type) as IPaymentService;
            }
            catch (Exception ex)
            {
                throw new PaymentException(PaymentExceptionType.LoadPayEntryFail,
                    string.Format(Resources.LoadPayEntryFail, paymentMode.TypeFullName), ex);
            }

            if (payEntry == null)
            {
                throw new PaymentException(PaymentExceptionType.LoadPayEntryFail,
                    string.Format(Resources.LoadPayEntryFail, paymentMode.TypeFullName));
            }

            return payEntry;
        }

        #endregion
    }
}
